home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / abuse / src / cop.c < prev    next >
C/C++ Source or Header  |  1996-04-12  |  28KB  |  1,082 lines

  1. #include "lisp.hpp"
  2. #include "lisp_gc.hpp"
  3. #include "compiled.hpp"
  4. #include "objects.hpp"
  5. #include "level.hpp"
  6. #include "game.hpp"
  7. #include "jrand.hpp"
  8. #include "clisp.hpp"
  9. #include "ant.hpp"
  10.  
  11. enum { point_angle, fire_delay1 };
  12.  
  13. #define SHOTGUN  10
  14. #define GRENADE  2
  15. #define ROCKET   3
  16. #define PLASMA   4
  17. #define FIREBOMB 5
  18. #define DFRIS    6
  19. #define LSABER   7
  20.  
  21. extern int registered;
  22.  
  23. signed char small_fire_off[24*2]=  // x & y offset from character to end of gun.
  24.   { 17,20,     // 1
  25.     17,23,     // 2
  26.     17,28,     
  27.     15,33,     
  28.     11,39,     // 5
  29.     7,43,
  30.     -3,44,     // 7
  31.     -10,42,    
  32.     -16,39,
  33.     -20,34,
  34.     -20,28,
  35.     -20,25,
  36.     -19,20,
  37.     -19,16,
  38.     -16,14,
  39.     -14,11,
  40.     -11,9,
  41.     -7,8,
  42.     -3,8,
  43.     2,8,
  44.     6,9,
  45.     10,10,
  46.     14,13,
  47.     16,15 };
  48.  
  49. signed char large_fire_off[24*2]=
  50.   { 18,25,
  51.     17,30,
  52.     15,34,
  53.     14,36,
  54.     10,39,
  55.     7,41,
  56.     4,42,
  57.     -3,41,
  58.     -8,39,
  59.     -11,37,
  60.     -14,33,
  61.     -16,30,
  62.     -18,25,
  63.     -17,21,
  64.     -14,17,
  65.     -11,15,
  66.     -7,13,
  67.     -4,12,
  68.     3,12,
  69.     9,12,
  70.     12,15,
  71.     14,16,
  72.     15,18,
  73.     16,21 };
  74.   
  75.  
  76. enum { in_climbing_area,
  77.     disable_top_draw,
  78.     just_hit,
  79.     ship_pan_x,
  80.     special_power,
  81.     used_special_power,
  82.     last1_x, last1_y,
  83.     last2_x, last2_y,
  84.     has_saved_this_level,
  85.     r_ramp, g_ramp, b_ramp,
  86.         is_teleporting,
  87.        just_fired};
  88.  
  89.  
  90. enum { sgb_speed,
  91.        sgb_angle,
  92.        sgb_lastx,
  93.        sgb_lasty,
  94.        sgb_bright_color,
  95.        sgb_medium_color,
  96.        sgb_lifetime };
  97.  
  98. enum { NO_POWER,
  99.        FAST_POWER,
  100.        FLY_POWER,
  101.        SNEAKY_POWER,
  102.        HEALTH_POWER } ;
  103.  
  104. enum { top_point_angle, 
  105.        top_fire_delay1, 
  106.        top_just_fired };
  107.  
  108. inline int angle_diff(int a1, int a2)
  109. {
  110.   if (a1<a2)
  111.   { if ((a2-a1)<180)
  112.       return a2-a1;
  113.     else return 360-a2+a1;
  114.   } else
  115.   {
  116.     if ((a1-a2)<180)
  117.       return a1-a2;
  118.     else return 360-a1+a2;
  119.   }
  120.   return 0;
  121. }
  122.  
  123. extern char *symbol_str(char *name);
  124.  
  125. void *top_ai()
  126. {
  127.   game_object *o=current_object;
  128.   if (o->total_objects())            // make sure we are linked to the main character
  129.   {  
  130.     game_object *q=o->get_object(0);
  131.  
  132.     view *v=q->controller();
  133.     if (v)
  134.     {
  135.       if (!v->freeze_time)
  136.       {
  137.     o->direction=1;                 // always face right
  138.  
  139.     if (q->direction<0)
  140.           q->x+=4;
  141.     int i; 
  142.     signed char *fire_off=o->otype==S_DFRIS_TOP ? large_fire_off :
  143.                                     (o->otype==S_ROCKET_TOP ? large_fire_off :
  144.                      (o->otype==S_BFG_TOP ? large_fire_off : small_fire_off));
  145.     signed char *f=fire_off,*fb;
  146.     int best_diff=200,best_num;
  147.     int iy=f[1],ix=f[6*2];
  148.     
  149.     int best_angle=lisp_atan2(q->y-iy-v->pointer_y,v->pointer_x-q->x-ix);
  150.     for (i=0;i<24;i++,f+=2)             // check all the angles to see which would best fit animation wise
  151.     {
  152.       int this_angle=lisp_atan2(f[1]-iy,f[0]-ix);
  153.       int this_diff=angle_diff(this_angle,best_angle);
  154.       if (this_diff<best_diff)
  155.       {
  156.         best_diff=this_diff;
  157.         best_num=i;
  158.         fb=f;
  159.       }
  160.     }
  161.  
  162.  
  163.     // if the pointer is too close to the player go with the angle shown, not the angle through the pointer
  164.     if (abs(q->y-fb[1]-v->pointer_y)<45 & abs(v->pointer_x-q->x+fb[0])<40)
  165.       o->lvars[point_angle]=lisp_atan2(fb[1]-iy,fb[0]-ix);
  166.     else
  167.       o->lvars[point_angle]=lisp_atan2(q->y-fb[1]-v->pointer_y,v->pointer_x-(q->x+fb[0]));
  168.     
  169.  
  170.     if (q->direction<0)
  171.           q->x-=4;
  172.  
  173.     o->x=q->x;
  174.     o->y=q->y+29-q->picture()->height();
  175.  
  176.     rand_on+=o->lvars[point_angle];
  177.     o->current_frame=best_num;
  178.  
  179.  
  180.     if (o->lvars[fire_delay1])
  181.       o->lvars[fire_delay1]--;
  182.  
  183.     o->otype=weapon_types[v->current_weapon];  // switch to correct top part    
  184.       }
  185.     }
  186.   }
  187.   return true_symbol;
  188. }
  189.  
  190.  
  191. int player_fire_weapon(game_object *o, int type, game_object *target, int angle, signed char *fire_off)
  192. {
  193.  
  194.   if (!o->total_objects()) return 0;
  195.   game_object *other=o->get_object(0);
  196.   int ox=other->x,oy=other->y;
  197.   if (other->direction<0) other->x+=4;
  198.  
  199.   int firex=other->x+fire_off[o->current_frame*2];
  200.   int firey=other->y-fire_off[o->current_frame*2+1];
  201.  
  202.  
  203.  
  204.   // fire try to move up to gun level
  205.  
  206.   long x2=o->x,y2=firey;
  207. //  current_level->foreground_intersect(other->x,other->y,x2,y2);      // find first location we can actuall "see"
  208. //  current_level->all_boundary_setback(o,other->x,other->y,x2,y2);       // to make we don't fire through walls
  209.   other->y=y2;
  210.  
  211.   if (other->y==firey)             // now try to move out to end of gun if we were not blocked above
  212.   {
  213.     x2=firex;
  214.     current_level->foreground_intersect(other->x,other->y,x2,y2);      // find first location we can actuall "see"
  215.     current_level->all_boundary_setback(other,other->x,other->y,x2,y2);       // to make we don't fire through walls
  216.     o->x=x2;
  217.   }
  218.  
  219.   void *list=NULL;
  220.   p_ref r1(list);
  221.   push_onto_list(new_lisp_pointer(target),list);
  222.   push_onto_list(new_lisp_number(angle),list);
  223.   push_onto_list(new_lisp_number(y2),list);
  224.   push_onto_list(new_lisp_number(x2),list);
  225.   push_onto_list(new_lisp_number(type),list);
  226.   push_onto_list(new_lisp_pointer(o->get_object(0)),list);
  227.   eval_function((lisp_symbol *)l_fire_object,list);
  228.   o->lvars[top_just_fired]=1;
  229.   other->lvars[just_fired]=1;
  230.   other->x=ox;
  231.   other->y=oy;
  232.  
  233.   return 1;
  234. }
  235.  
  236.  
  237.  
  238. void *laser_ufun(void *args)
  239. {
  240.   game_object *o=current_object;
  241.   p_ref r1(args);
  242.   void *signal=CAR(args);  args=CDR(args);
  243.   void *ret=NULL;
  244.  
  245.   if (signal==l_FIRE)
  246.   {
  247.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  248.     {
  249.       long value=lnumber_value(eval(CAR(args)));
  250.       if (value)                                   // do we have ammo ?
  251.       {
  252.     o->lvars[fire_delay1]=3;
  253.     if (player_fire_weapon(o,SHOTGUN,NULL,o->lvars[point_angle],small_fire_off))
  254.           ret=new_lisp_number(-1);
  255.     else ret=new_lisp_number(0);
  256.       } else
  257.       {
  258.     o->lvars[fire_delay1]=5;                  // no ammo, set large fire delay for next shot
  259.     player_fire_weapon(o,SHOTGUN,NULL,o->lvars[point_angle],small_fire_off);
  260.     ret=new_lisp_number(0);
  261.       }
  262.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  263.   }
  264.   return ret;
  265. }
  266.  
  267.  
  268. static int ammo_type(int otype)
  269. {
  270.   if (otype==S_GRENADE_TOP)
  271.     return GRENADE;
  272.   else if (otype==S_FIREBOMB_TOP)
  273.     return FIREBOMB;
  274.   else if (otype==S_DFRIS_TOP)
  275.     return DFRIS;
  276.   else return SHOTGUN;
  277. }
  278.  
  279.  
  280. void *top_ufun(void *args)                       // generic top character ai GRENADE && FIREBOMB
  281. {
  282.   game_object *o=current_object;
  283.   p_ref r1(args);
  284.   void *signal=CAR(args);  args=CDR(args);
  285.   void *ret=NULL;
  286.  
  287.   if (signal==l_FIRE)
  288.   {
  289.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  290.     {
  291.       long value=lnumber_value(eval(CAR(args)));
  292.       if (value)                                   // do we have ammo ?
  293.       {
  294.     o->lvars[fire_delay1]=6;
  295.     if (player_fire_weapon(o,ammo_type(o->otype),NULL,o->lvars[point_angle],
  296.                    o->otype==DFRIS ? large_fire_off : small_fire_off ))      
  297.           ret=new_lisp_number(-1);
  298.     else ret=new_lisp_number(0);
  299.       } else ret=new_lisp_number(0);
  300.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  301.   }
  302.   return ret;
  303. }
  304.  
  305. static int climb_handler(game_object *, int xm, int ym, int but);
  306.  
  307. void *plaser_ufun(void *args)
  308. {
  309.   game_object *o=current_object;
  310.   p_ref r1(args);
  311.   void *signal=CAR(args);  args=CDR(args);
  312.   void *ret=NULL;
  313.  
  314.   if (signal==l_FIRE)
  315.   {
  316.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  317.     {
  318.       long value=lnumber_value(eval(CAR(args)));
  319.       if (value)                                   // do we have ammo ?
  320.       {
  321.     o->lvars[fire_delay1]=2;
  322.     if (player_fire_weapon(o,PLASMA,NULL,o->lvars[point_angle],small_fire_off))      
  323.           ret=new_lisp_number(-1);
  324.     else ret=new_lisp_number(0);
  325.       } else ret=new_lisp_number(0);
  326.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  327.   }
  328.   return ret;
  329. }
  330.  
  331. void *lsaber_ufun(void *args)
  332. {
  333.   game_object *o=current_object;
  334.   p_ref r1(args);
  335.   void *signal=CAR(args);  args=CDR(args);
  336.   void *ret=NULL;
  337.  
  338.   if (signal==l_FIRE)
  339.   {
  340.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  341.     {
  342.       long value=lnumber_value(eval(CAR(args)));
  343.       if (value)                                   // do we have ammo ?
  344.       {
  345.     o->lvars[fire_delay1]=1;
  346.     if (player_fire_weapon(o,LSABER,NULL,o->lvars[point_angle]+(current_level->tick_counter()&7)-8,
  347.                    small_fire_off))
  348.           ret=new_lisp_number(-1);
  349.     else ret=new_lisp_number(0);
  350.       } else ret=new_lisp_number(0);
  351.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  352.   }
  353.   return ret;
  354. }
  355.  
  356.  
  357.  
  358. void *player_rocket_ufun(void *args)
  359. {
  360.   game_object *o=current_object;
  361.   p_ref r1(args);
  362.   void *signal=CAR(args);  args=CDR(args);
  363.   void *ret=NULL;
  364.   int xd,yd,cl=0xfffffff,d;
  365.   if (signal==l_FIRE)
  366.   {
  367.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  368.     {
  369.       long value=lnumber_value(eval(CAR(args)));
  370.       if (value)                                   // do we have ammo ?
  371.       {
  372.     o->lvars[fire_delay1]=6;
  373.     game_object *target=NULL,*p,*bot=o->total_objects() ? o->get_object(0) : 0;
  374.     if (bad_guy_array)
  375.     {
  376.       game_object *other=current_object->total_objects() ? current_object->get_object(0) : 0;
  377.       for (p=current_level->first_active_object();p;p=p->next_active)
  378.       {
  379.         xd=abs(p->x-o->x);
  380.         yd=abs(p->y-o->y);
  381.         if (xd<160 && yd<130 && bad_guy_array[p->otype] && p!=other)
  382.         {
  383.           if (p->targetable() &&          
  384.           !(p->otype==S_ROCKET && p->total_objects() && p->get_object(0)==bot))  // don't track onto own missles
  385.           {
  386.         d=xd*xd+yd*yd;
  387.         if (d<cl)
  388.         {
  389.           cl=d;
  390.           target=p;
  391.         }
  392.           }
  393.         }
  394.       }
  395.     }
  396.     if (player_fire_weapon(o,ROCKET,target,o->lvars[point_angle],large_fire_off))      
  397.           ret=new_lisp_number(-1);
  398.     else ret=new_lisp_number(0);
  399.  
  400.       } else ret=new_lisp_number(0);
  401.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  402.   }
  403.   return ret;
  404. }
  405.  
  406. static int player_move(game_object *o, int xm, int ym, int but)
  407. {
  408.   if (!o->lvars[in_climbing_area])
  409.   {
  410.     if (o->state==S_climbing)
  411.     {
  412.       o->set_gravity(1);
  413.       o->set_state(run_jump_fall);
  414.     }
  415.     o->next_picture();
  416.     return o->mover(xm,ym,but);
  417.   } else return climb_handler(o,xm,ym,but);
  418.      
  419. }
  420.  
  421.  
  422. static void undo_special_power(game_object *o)
  423. {
  424.   switch (o->lvars[special_power])
  425.   {
  426.     case SNEAKY_POWER :
  427.     {
  428.       if (o->lvars[used_special_power]>0)
  429.         o->lvars[used_special_power]--;
  430.     } break;
  431.     case FAST_POWER :
  432.     {
  433.       o->lvars[used_special_power]=0;
  434.     } break;
  435.   }
  436. }
  437.  
  438. static void do_special_power(game_object *o, int xm, int ym, int but, game_object *top)
  439. {
  440.   switch (o->lvars[special_power])
  441.   {
  442.     case FLY_POWER :
  443.     {
  444.       if (registered)
  445.       {
  446.     game_object *cloud=create(S_CLOUD,o->x+o->direction*-10,o->y+jrand()%5);
  447.     if (current_level)
  448.         current_level->add_object(cloud);
  449.     o->set_state(run_jump);
  450.     o->set_gravity(1);
  451.     o->set_yacel(0);
  452.     if (o->yvel()>0) o->set_yvel(o->yvel()/2);
  453.     if (ym<0) 
  454.         o->set_yvel(o->yvel()-3);
  455.     else
  456.         o->set_yvel(o->yvel()-2);
  457.     the_game->play_sound(S_FLY_SND,32,o->x,o->y);
  458.       }
  459.     } break;
  460.     case FAST_POWER :
  461.     {
  462.       if ((current_level->tick_counter()%16)==0)
  463.       the_game->play_sound(S_SPEED_SND,100,o->x,o->y);
  464.  
  465.       o->lvars[used_special_power]=1;
  466.       o->lvars[last1_x]=o->x;
  467.       o->lvars[last1_y]=o->y;
  468.       long oyvel=o->yvel();
  469.       int in=o->lvars[in_climbing_area];
  470.       int ok;
  471.  
  472.  
  473.       player_move(o,xm,ym,but);
  474.       if (ym<0 && !oyvel && o->yvel()<0)             // if they just jumped, make them go higher
  475.       o->set_yvel(o->yvel()+o->yvel()/3);
  476.       o->lvars[in_climbing_area]=in;
  477.  
  478.       o->lvars[last2_x]=o->x;
  479.       o->lvars[last2_x]=o->y;
  480.     } break;
  481.     case SNEAKY_POWER :
  482.     {
  483.       if (registered)
  484.       {
  485.     if (o->lvars[used_special_power]<15)
  486.           o->lvars[used_special_power]++;
  487.       }
  488.     } break;
  489.   }
  490. }
  491.  
  492. static int climb_off_handler(game_object *o)
  493. {
  494.   if (o->next_picture())
  495.     o->controller()->pan_y-=4;
  496.   else
  497.   {
  498.     o->y-=28;
  499.     o->controller()->pan_y+=28;
  500.     o->controller()->last_y-=28;
  501.     o->set_state(stopped);
  502.   }
  503.   return 0;
  504. }
  505.  
  506.  
  507. static int climb_on_handler(game_object *o)
  508. {
  509.   if (o->next_picture())
  510.     o->controller()->pan_y+=4;
  511.   else
  512.     o->set_state((character_state)S_climbing);
  513.   return 0;
  514. }
  515.  
  516. static int climb_handler(game_object *o, int xm, int ym, int but)
  517. {
  518.   int yd=o->lvars[in_climbing_area];  // see how from the top we are
  519.   o->lvars[in_climbing_area]=0;          // set 0, ladders will set back to proper if still in area
  520.   if (o->state==S_climb_off)
  521.     climb_off_handler(o);
  522.   else if (o->state==S_climb_on)
  523.     climb_on_handler(o);  
  524.   else
  525.   {
  526.     if (o->state==S_climbing)
  527.     {
  528.       if (ym>0)                       // going down
  529.       {
  530.  
  531.     if (o->current_frame==0) o->current_frame=9;
  532.       o->current_frame--;    
  533.  
  534. /*    if (o->lvars[special_power]==FAST_POWER)
  535.     {
  536.       long xv=0,yv=4;
  537.       o->try_move(o->x,o->y,xv,yv,1);
  538.       if (yv==4)
  539.         o->y+=3;
  540.       else 
  541.       {
  542.         o->set_gravity(1);
  543.           o->set_state(run_jump_fall);
  544.       }
  545.     }
  546.     else */ o->y+=3;
  547.     
  548.  
  549.       } else if (ym<0)
  550.       {
  551.     if (yd<32)
  552.       o->set_state((character_state)S_climb_off);
  553.     else
  554.     {
  555.       if (!o->next_picture()) o->set_state((character_state)S_climbing);
  556.       o->y-=3;
  557.     }
  558.       }
  559.       if (xm)                     // trying to get off the ladder, check to see if that's ok
  560.       {
  561.     long x2=0,y2=-20;
  562.     o->try_move(o->x,o->y,x2,y2,3);
  563.     if (y2==-20)
  564.     {
  565.       o->set_gravity(1);
  566.       if (ym>=0)
  567.         o->set_state(run_jump_fall);
  568.       else 
  569.       { o->set_state(run_jump);
  570.         o->set_yvel(get_ability(o->otype,jump_yvel));      
  571.       }
  572.     }
  573.       }
  574.     }  else if (ym>0 && yd<10)
  575.     {
  576.       o->y+=28;
  577.       o->controller()->pan_y-=28;
  578.       o->controller()->last_y+=28;
  579.       o->set_state((character_state)S_climb_on);
  580.     }
  581.     else if (o->yvel()>=0 && (ym>0 || (ym<0 && yd>8)))
  582.     {
  583.       o->set_state((character_state)S_climbing);
  584.       o->set_gravity(0);
  585.       o->set_xvel(0);
  586.       o->set_yvel(0);
  587.       o->set_xacel(0);
  588.       o->set_yacel(0);
  589.       return 0;
  590.     } else 
  591.     { 
  592.       o->next_picture();
  593.       return o->mover(xm,ym,but);
  594.     }
  595.   }
  596.   return 0;
  597. }
  598.  
  599.  
  600. void *cop_mover(int xm, int ym, int but)
  601. {
  602.  
  603.   int ret=0;
  604.   game_object *o=current_object,*top;
  605.   if (o->controller() && o->controller()->freeze_time)  
  606.   {
  607.     o->controller()->freeze_time--;
  608.     if (but || o->controller()->key_down(JK_SPACE) || o->controller()->key_down(JK_ENTER)) 
  609.       o->controller()->freeze_time=0;
  610.   }
  611.   else
  612.   {
  613.     if (!o->total_objects())                  // if no top create one
  614.     {
  615.       top=create(S_MGUN_TOP,o->x,o->y,0,0);
  616.       current_level->add_object_after(top,o);    
  617.       o->add_object(top);
  618.       top->add_object(o);
  619.     } else top=o->get_object(0);
  620.  
  621.     if (o->yvel()>10) 
  622.     {
  623.       o->set_yacel(0);
  624.       o->set_yvel(o->yvel()-1);            // terminal velocity
  625.     }
  626.  
  627.     if (o->aistate()==0)  // just started, wait for button
  628.     {
  629.       o->set_aistate(1);    
  630.     } else if (o->aistate()==1)         // normal play
  631.     {
  632.       if (o->hp()==0)
  633.       {
  634.     o->set_aistate(2);                // go to deing state
  635.     o->set_state(dead);    
  636.       }
  637.       else
  638.       {
  639.     if (o->hp()<40 && (current_level->tick_counter()%16)==0) // if low on health play heart beat    
  640.       the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
  641.     else if (o->hp()<15 && (current_level->tick_counter()%8)==0) // if low on health play heart beat
  642.       the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
  643.     else if (o->hp()<7 && (current_level->tick_counter()%4)==0) // if low on health play heart beat
  644.       the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
  645.  
  646.     if (but&1)
  647.         do_special_power(o,xm,ym,but,top);
  648.     else
  649.     undo_special_power(o);
  650.     ret=player_move(o,xm,ym,but);
  651.     top->x=o->x;
  652.     top->y=o->y+29-top->picture()->height();
  653.     
  654.     if ((but&2) && !o->lvars[is_teleporting] && o->state!=S_climbing && o->state!=S_climb_off)
  655.     {
  656.       void *args=NULL;
  657.       p_ref r1(args);
  658.       view *v=o->controller();
  659.  
  660.       push_onto_list(new_lisp_number(v->weapon_total(v->current_weapon)),args);
  661.       push_onto_list(l_FIRE,args);
  662.  
  663.       current_object=top;
  664.       void *ret=eval_function((lisp_symbol *)figures[top->otype]->get_fun(OFUN_USER_FUN),args);      
  665.       current_object=o;
  666.       v->add_ammo(v->current_weapon,lnumber_value(ret));    
  667.     }
  668.       }    
  669.     } else if (o->aistate()==3)
  670.     {
  671.       if (!o->controller() || o->controller()->key_down(JK_SPACE))
  672.       {
  673.     eval_function((lisp_symbol *)l_restart_player,NULL);  // call teh user function to reset the player
  674.     o->controller()->reset_player();
  675.     o->set_aistate(0);     
  676.       } else if (o->controller() && o->controller()->local_player())
  677.         the_game->show_help(symbol_str("space_cont"));
  678.  
  679.     } else o->set_aistate(o->aistate()+1);
  680.   }
  681.  
  682.   return new_lisp_number(ret);
  683. }
  684.  
  685.  
  686.  
  687. void *ladder_ai()
  688. {
  689.   view *f=player_list;
  690.   game_object *o=current_object;
  691.   if (o->total_objects())
  692.   {
  693.     game_object *other=o->get_object(0);
  694.     for (;f;f=f->next)
  695.     {
  696.       int mex=f->focus->x;
  697.       int mey=f->focus->y;
  698.       
  699.       if (o->x<=mex && o->y<=mey && other->x>=mex && other->y>=mey)
  700.       {
  701.     if (f->focus->state==S_climbing)
  702.       f->focus->x=(o->x+other->x)/2;
  703.         f->focus->lvars[in_climbing_area]=mey-o->y;    
  704.       }
  705.     }
  706.   }
  707.   return true_symbol;
  708. }
  709.  
  710.  
  711.  
  712. void *player_draw(int just_fired_var, int num)
  713. {
  714.   game_object *o=current_object;
  715.   if (num==0) 
  716.   {
  717.     if (o->lvars[just_fired_var])
  718.     {
  719.       o->draw_tint(S_bright_tint);
  720.       o->lvars[just_fired_var]=0;
  721.     } else
  722.       o->drawer();
  723.   }
  724.   else 
  725.   {
  726.     if (o->lvars[just_fired_var])
  727.     {
  728.       o->draw_double_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)),S_bright_tint);
  729.       o->lvars[just_fired_var]=0;
  730.     } else
  731.       o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)));
  732.   }
  733.   return NULL;
  734. }
  735.  
  736.  
  737. void *top_draw()
  738. {
  739.   game_object *o=current_object;
  740.   if (o->total_objects())
  741.   {
  742.     game_object *bot=o->get_object(0);
  743.     if (bot->state==stopped  || bot->state==running || 
  744.     bot->state==run_jump || bot->state==run_jump_fall ||
  745.     bot->state==end_run_jump)
  746.     {
  747.       int oldy=o->y;
  748.       o->x=bot->x;
  749.       if (bot->direction<0)
  750.         o->x+=4;
  751.       o->y=bot->y+29-bot->picture()->height();
  752.  
  753.       void *ret=NULL;
  754.       p_ref r1(ret);
  755.  
  756.       push_onto_list(new_lisp_number(bot->controller()->player_number),ret);
  757.  
  758.       if (bot->lvars[special_power]==SNEAKY_POWER)
  759.       {
  760.     if (bot->lvars[used_special_power]==0)
  761.       player_draw(top_just_fired,bot->controller()->player_number);
  762.     else if (bot->lvars[used_special_power]<15)
  763.       o->draw_trans(bot->lvars[used_special_power],16);
  764.     else
  765.       o->draw_predator();
  766.       } else
  767.         eval_function((lisp_symbol *)l_player_draw,ret);
  768.       
  769.       o->y=oldy;
  770.       if (bot->direction<0)
  771.         o->x-=4;
  772.     }
  773.   }
  774.   return NULL;
  775. }
  776.  
  777.  
  778.  
  779. void *bottom_draw()
  780. {
  781.   game_object *o=current_object;
  782.  
  783.   if (o->lvars[r_ramp] || o->lvars[g_ramp] || o->lvars[b_ramp])
  784.   {
  785.     int r=o->lvars[r_ramp];
  786.     if (r>7) r-=7;
  787.     else r=0;
  788.     o->lvars[r_ramp]=r;
  789.  
  790.     int g=o->lvars[g_ramp];
  791.     if (g>7) g-=7;
  792.     else g=0;
  793.     o->lvars[g_ramp]=g;
  794.  
  795.     int b=o->lvars[b_ramp];
  796.     if (b>7) b-=7;
  797.     else b=0;
  798.     o->lvars[b_ramp]=b;
  799.  
  800.     palette *p=pal->copy();
  801.     uchar *addr=(uchar *)p->addr();
  802.     int ra,ga,ba;
  803.     
  804.     for (int i=0;i<256;i++)
  805.     {
  806.       ra=(int)*addr+r; if (ra>255) ra=255; else if (ra<0) r=0; *addr=(uchar)ra; addr++;
  807.       ga=(int)*addr+g; if (ga>255) ga=255; else if (ga<0) g=0; *addr=(uchar)ga; addr++;
  808.       ba=(int)*addr+b; if (ba>255) ba=255; else if (ba<0) b=0; *addr=(uchar)ba; addr++;
  809.     }
  810.     p->load();
  811.     delete p;
  812.   }
  813.  
  814.   if (o->aistate()>0)
  815.   {
  816.     switch (o->lvars[special_power])
  817.     {
  818.       case NO_POWER : 
  819.       { player_draw(just_fired,o->controller()->player_number); } break;
  820.  
  821.       case HEALTH_POWER :
  822.       {
  823.     player_draw(just_fired,o->controller()->player_number);
  824.     if (o->controller() && o->controller()->local_player())
  825.       cash.img(S_health_image)->put_image(screen,o->controller()->cx2-20,
  826.                         o->controller()->cy1+5,1);
  827.       } break;
  828.       case FAST_POWER :
  829.       {
  830.     eval_function((lisp_symbol *)l_draw_fast,NULL);
  831.     int old_state=o->state;
  832.     switch (o->state)
  833.     {
  834.       case stopped : o->state=(character_state)S_fast_stopped; break;
  835.       case running : o->state=(character_state)S_fast_running; break;
  836.       case start_run_jump : o->state=(character_state)S_fast_start_run_jump; break;
  837.       case run_jump : o->state=(character_state)S_fast_run_jump; break;
  838.       case run_jump_fall : o->state=(character_state)S_fast_run_jump_fall; break;
  839.       case end_run_jump : o->state=(character_state)S_fast_end_run_jump; break;
  840.     }
  841.  
  842.     player_draw(just_fired,o->controller()->player_number);
  843.     o->state=(character_state)old_state;
  844.     if (o->controller() && o->controller()->local_player())
  845.       cash.img(S_fast_image)->put_image(screen,o->controller()->cx2-20,
  846.                         o->controller()->cy1+5,1);
  847.       } break;
  848.       case FLY_POWER :
  849.       {
  850.     int old_state=o->state;
  851.     switch (o->state)
  852.     {
  853.       case stopped : o->state=(character_state)S_fly_stopped; break;
  854.       case running : o->state=(character_state)S_fly_running; break;
  855.       case start_run_jump : o->state=(character_state)S_fly_start_run_jump; break;
  856.       case run_jump : o->state=(character_state)S_fly_run_jump; break;
  857.       case run_jump_fall : o->state=(character_state)S_fly_run_jump_fall; break;
  858.       case end_run_jump : o->state=(character_state)S_fly_end_run_jump; break;
  859.     }
  860.  
  861.     player_draw(just_fired,o->controller()->player_number);
  862.     o->state=(character_state)old_state;
  863.  
  864.     if (o->controller() && o->controller()->local_player())
  865.       cash.img(S_fly_image)->put_image(screen,o->controller()->cx2-20,
  866.                         o->controller()->cy1+5,1);
  867.       } break;
  868.       case SNEAKY_POWER :
  869.       {
  870.     if (o->lvars[used_special_power]==0)
  871.       player_draw(just_fired,o->controller()->player_number);
  872.     else if (o->lvars[used_special_power]<15)
  873.       o->draw_trans(o->lvars[used_special_power],16);
  874.     else
  875.       o->draw_predator();
  876.       
  877.     if (o->controller() && o->controller()->local_player())
  878.       cash.img(S_sneaky_image)->put_image(screen,o->controller()->cx2-20,
  879.                         o->controller()->cy1+5,1);
  880.       } break;
  881.     }    
  882.   }
  883.   return NULL;
  884. }
  885.  
  886.  
  887.  
  888. void *sgun_ai()
  889. {
  890.   game_object *o=current_object;
  891.  
  892.   if (o->lvars[sgb_lifetime]==0)
  893.     return NULL;
  894.   o->lvars[sgb_lifetime]--;
  895.  
  896.   o->lvars[sgb_lastx]=o->x;
  897.   o->lvars[sgb_lasty]=o->y;
  898.   o->lvars[sgb_speed]=o->lvars[sgb_speed]*6/5;
  899.   
  900.   long ang=o->lvars[sgb_angle];
  901.   long mag=o->lvars[sgb_speed];
  902.  
  903.   long xvel=(lisp_cos(ang))*(mag);
  904.   current_object->set_xvel(xvel>>16);
  905.   current_object->set_fxvel((xvel&0xffff)>>8);
  906.   long yvel=-(lisp_sin(ang))*(mag);
  907.   current_object->set_yvel(yvel>>16);
  908.   current_object->set_fyvel((yvel&0xffff)>>8);      
  909.  
  910.  
  911.   int whit=0;
  912.   game_object *who=o->bmove(whit, o->total_objects() ? o->get_object(0) : 0);
  913.  
  914.   if (whit || (who && figures[who->otype]->get_cflag(CFLAG_UNACTIVE_SHIELD) && who->total_objects() &&
  915.            who->get_object(0)->aistate()==0))
  916.   {
  917.     o->lvars[sgb_lifetime]=0;
  918.     game_object *n=create(S_EXPLODE5,o->x+jrand()%4,o->y+jrand()%4);
  919.     current_level->add_object(n);    
  920.   } else if (who && figures[who->otype]->get_cflag(CFLAG_HURTABLE))
  921.   {
  922.     o->lvars[sgb_lifetime]=0;
  923.     game_object *n=create(S_EXPLODE3,o->x+jrand()%4,o->y+jrand()%4);
  924.     current_level->add_object(n);        
  925.      who->do_damage(5,o,o->x,o->y,(lisp_cos(ang)*10)>>16,(lisp_sin(ang)*10)>>16);
  926.   }
  927.   return true_symbol;
  928. }
  929.  
  930.  
  931.  
  932. void *mover_ai()
  933. {
  934.   game_object *o=current_object;
  935.   if (o->total_objects()==2)
  936.   {
  937.     if (o->aistate()<2) 
  938.     {
  939.       game_object *obj=o->get_object(1);
  940.       o->remove_object(obj);
  941.       game_object *d=o->get_object(0);
  942.       d->add_object(obj);
  943.       d->set_aistate(d->aitype());
  944.     } else
  945.     {
  946.       o->set_aistate(o->aistate()-1);
  947.       game_object *d=o->get_object(0);
  948.       game_object *obj=o->get_object(1);      
  949.  
  950.       obj->x=d->x-(d->x-o->x)*o->aistate()/o->aitype();
  951.       obj->y=d->y-(d->y-o->y)*o->aistate()/o->aitype();
  952.     }
  953.   }
  954.   return true_symbol;
  955. }    
  956.  
  957.  
  958. void *respawn_ai()
  959.  game_object *o=current_object;
  960.  int x=o->total_objects();
  961.  if (x)
  962.  {
  963.    game_object *last=o->get_object(x-1);
  964.    if (last->x==o->x && last->y==o->y)
  965.    {
  966.      if (last->fade_count())
  967.        last->set_fade_count(last->fade_count()-1);
  968.      o->set_aistate_time(0);
  969.    } else if (o->aistate_time()>o->xvel())
  970.    {
  971.      int type=o->get_object(jrandom(x))->otype;
  972.      game_object *n=create(type,o->x,o->y);
  973.      current_level->add_object(n);
  974.      o->add_object(n);
  975.      n->set_fade_count(15);
  976.      o->set_aistate_time(0);
  977.    } 
  978.  }
  979.  return true_symbol;
  980. }
  981.  
  982. static int compare_players(const void *a, const void *b)
  983. {
  984.   if  ( ((view **)a)[0]->kills > ((view **)b)[0]->kills) 
  985.     return -1;
  986.   else if  ( ((view **)a)[0]->kills < ((view **)b)[0]->kills) 
  987.     return 1;
  988.   else if (((view **)a)[0]->player_number > ((view **)b)[0]->player_number)
  989.     return -1;
  990.   else if (((view **)a)[0]->player_number < ((view **)b)[0]->player_number)
  991.     return 1;
  992.   else return 0;  
  993. }
  994.  
  995. void *score_draw()
  996. {
  997.   view *sorted_players[16],*local=NULL;
  998.   int tp=0;
  999.   view *f=player_list;
  1000.   for (;f;f=f->next) 
  1001.   { 
  1002.     sorted_players[tp]=f;
  1003.     tp++;
  1004.     if (f->local_player()) local=f;
  1005.   }
  1006.  
  1007.   JCFont *fnt=eh->font();
  1008.   if (local)
  1009.   {
  1010.     qsort(sorted_players,tp,sizeof(view *),compare_players);
  1011.  
  1012.     int x=local->cx1;
  1013.     int y=local->cy1;
  1014.     char msg[100];
  1015.  
  1016.     int i;
  1017.     for (i=0;i<tp;i++)
  1018.     {
  1019.       int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),sorted_players[i]->player_number));  
  1020.       sprintf(msg,"%3d %s",sorted_players[i]->kills,sorted_players[i]->name);
  1021.       if (sorted_players[i]==local)
  1022.         strcat(msg," <<");
  1023.  
  1024.       fnt->put_string(screen,x,y,msg,color);
  1025.       y+=fnt->height();
  1026.     }
  1027.   }
  1028.   return NULL;
  1029. }
  1030.  
  1031.  
  1032. extern void fade_in(image *im, int steps);
  1033. extern void fade_out(int steps);
  1034.  
  1035. void *show_kills()
  1036. {
  1037.   fade_out(8);
  1038.   eh->set_mouse_position(0,0);
  1039.   screen->clear();
  1040.   image *im=cash.img(cash.reg("art/frame.spe","end_level_screen",SPEC_IMAGE,1));
  1041.   im->put_image(screen,0,0);
  1042.   int x1=im->width()+1,y1=0,x2=xres,y2=screen->height();
  1043.   JCFont *fnt=eh->font();
  1044.   
  1045.   view *v=player_list; int tp=0,i;
  1046.   for (v=player_list;v;v=v->next) tp++;
  1047.  
  1048.   int y=(y1+y2)/2-(tp+2)*fnt->height()/2,x=x1+10;
  1049.   char *header_str=symbol_str("score_header");
  1050.   fnt->put_string(screen,x,y,header_str,eh->bright_color());
  1051.   y+=fnt->height();
  1052.  
  1053.   screen->wiget_bar(x,y+2,x+strlen(header_str)*fnt->width(),y+fnt->height()-3,
  1054.              eh->bright_color(),eh->medium_color(),eh->dark_color());
  1055.   y+=fnt->height();
  1056.   v=player_list;
  1057.   for (i=0;i<tp;i++)
  1058.   {
  1059.     enum { NAME_LEN=18 } ;
  1060.     int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),v->player_number));  
  1061.     char max_name[NAME_LEN];
  1062.     strncpy(max_name,v->name,NAME_LEN-1);
  1063.     max_name[NAME_LEN-1]=0;
  1064.     char msg[100];
  1065.  
  1066.  
  1067.     sprintf(msg,"%-17s %3d  %3d",max_name,v->kills,v->tkills+v->kills);
  1068.     fnt->put_string(screen,x,y,msg,color);
  1069.  
  1070.     y+=fnt->height();
  1071.     v=v->next;
  1072.   }
  1073.   
  1074.   eh->flush_screen();
  1075.   milli_wait(4000);   // wait 4 seconds
  1076.  
  1077.   return NULL;
  1078. }
  1079.  
  1080.  
  1081.